package com.atguigu.daijia.order.service.impl;

import com.atguigu.daijia.common.constant.RedisConstant;
import com.atguigu.daijia.common.execption.GuiguException;
import com.atguigu.daijia.common.result.ResultCodeEnum;
import com.atguigu.daijia.model.entity.order.*;
import com.atguigu.daijia.model.enums.OrderStatus;
import com.atguigu.daijia.model.form.order.OrderInfoForm;
import com.atguigu.daijia.model.form.order.StartDriveForm;
import com.atguigu.daijia.model.form.order.UpdateOrderBillForm;
import com.atguigu.daijia.model.form.order.UpdateOrderCartForm;
import com.atguigu.daijia.model.vo.base.PageVo;
import com.atguigu.daijia.model.vo.order.*;
import com.atguigu.daijia.order.mapper.OrderBillMapper;
import com.atguigu.daijia.order.mapper.OrderInfoMapper;
import com.atguigu.daijia.order.mapper.OrderProfitsharingMapper;
import com.atguigu.daijia.order.mapper.OrderStatusLogMapper;
import com.atguigu.daijia.order.service.OrderInfoService;
import com.atguigu.daijia.order.service.OrderMonitorService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@SuppressWarnings({"unchecked", "rawtypes"})
@RequiredArgsConstructor
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    private final RedisTemplate redisTemplate;
    private final OrderStatusLogMapper orderStatusLogMapper;
    private final RedissonClient redissonClient;
    private final OrderMonitorService orderMonitorService;
    private final OrderBillMapper orderBillMapper;
    private final OrderProfitsharingMapper orderProfitsharingMapper;
    private final OrderInfoMapper orderInfoMapper;

    /**
     * 保存订单信息
     *
     * @param orderInfoForm
     * @return
     */
    @Transactional
    @Override
    public Long saveOrderInfo(OrderInfoForm orderInfoForm) {
        // 向 daijia_order 数据库 order_info 表中保存订单信息
        OrderInfo orderInfo = new OrderInfo();
        BeanUtils.copyProperties(orderInfoForm, orderInfo);
        String orderNo = UUID.randomUUID().toString().replaceAll("-", "");
        orderInfo.setOrderNo(orderNo);
        orderInfo.setStatus(OrderStatus.WAITING_ACCEPT.getStatus());
        this.save(orderInfo);

        // 记录订单状态日志到数据库
        this.log(orderInfo.getId(), orderInfo.getStatus());

        // 向 Redis 中添加标记，标识当前订单可以被司机抢单
        // 过期时间 15 分钟，新订单 15 分钟没有司机接单，系统自动取消订单，自然也不需要再维护这个标记
        redisTemplate.opsForValue().set(RedisConstant.ORDER_ACCEPT_MARK + orderInfo.getId(), "0", RedisConstant.ORDER_ACCEPT_MARK_EXPIRES_TIME, TimeUnit.MINUTES);

        // 生成订单需要发送延迟消息，方便在超过 15 分钟后没有司机接单时，取消订单
        this.sendDelayMessage(orderInfo.getId());
        
        return orderInfo.getId();
    }

    /**
     * 生成订单后，发送延迟消息
     * @param orderId
     */
    private void sendDelayMessage(Long orderId) {
        // 创建阻塞队列
        RBlockingQueue<Object> blockingQueue = redissonClient.getBlockingQueue(RedisConstant.ORDER_DELAY_QUEUE);
        // 创建延迟队列
        RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);
        // 添加消息（订单 ID）到延迟队列中，延迟时间 15 分钟
        delayedQueue.offer(orderId.toString(), RedisConstant.ORDER_DELAY_QUEUE_TIMEOUT, TimeUnit.MINUTES);
    }


    /**
     * 记录订单状态日志到数据库
     *
     * @param orderId
     * @param status
     */
    private void log(Long orderId, Integer status) {
        OrderStatusLog orderStatusLog = new OrderStatusLog();
        orderStatusLog.setOrderId(orderId);
        orderStatusLog.setOrderStatus(status);
        orderStatusLog.setOperateTime(new Date());
        orderStatusLogMapper.insert(orderStatusLog);
    }

    /**
     * 根据订单 ID 查询订单状态
     *
     * @param orderId
     * @return
     */
    @Override
    public Integer getOrderStatus(Long orderId) {
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getId, orderId);
        wrapper.select(OrderInfo::getStatus);
        OrderInfo orderInfo = this.getOne(wrapper);
        if (orderInfo == null) {
            // 订单不存在
            return OrderStatus.NULL_ORDER.getStatus();
        }
        return orderInfo.getStatus();
    }

    /**
     * 司机抢单
     *
     * @param driverId
     * @param orderId
     * @return
     */
    @Transactional
    @Override
    public Boolean robNewOrder(Long driverId, Long orderId) {
        // 司机抢单的前提是 ID 为 orderId 的订单记录存在。可以根据 orderId 查询数据库，但是如果同一时间有大量新订单产生，大量司机抢单过程中都去查询数据库，会导致数据库压力过大
        if (Boolean.FALSE.equals(redisTemplate.hasKey(RedisConstant.ORDER_ACCEPT_MARK + orderId))) {
            // 当前订单已被其他司机抢单，抢单失败
            throw new GuiguException(ResultCodeEnum.ROB_NEW_ORDER_FAIL);
        }

        // 获取 Redisson 分布式锁
        RLock lock = redissonClient.getLock(RedisConstant.ROB_NEW_ORDER_LOCK + orderId);

        try {
            // 尝试获取锁，最多等待 1 秒
            boolean flag = lock.tryLock(RedisConstant.ROB_NEW_ORDER_LOCK_WAIT_TIME, TimeUnit.SECONDS);

            if (!flag) {
                // 未能获取到锁，直接返回抢单失败
                throw new GuiguException(ResultCodeEnum.ROB_NEW_ORDER_FAIL);
            }

            // 使用乐观锁，保证只有第一个抢单的司机抢单成功
            boolean result = this.lambdaUpdate()
                    .eq(OrderInfo::getId, orderId)
                    .eq(OrderInfo::getStatus, OrderStatus.WAITING_ACCEPT.getStatus())
                    .set(OrderInfo::getStatus, OrderStatus.ACCEPTED.getStatus())
                    .set(OrderInfo::getAcceptTime, new Date())
                    .set(OrderInfo::getDriverId, driverId)
                    .update();
            if (!result) {
                // 抢单失败
                throw new GuiguException(ResultCodeEnum.ROB_NEW_ORDER_FAIL);
            }

            // 记录订单状态日志到数据库
            this.log(orderId, OrderStatus.ACCEPTED.getStatus());

            // 抢单成功，删除 Redis 中的抢单标记
            redisTemplate.delete(RedisConstant.ORDER_ACCEPT_MARK + orderId);
        } catch (Exception e) {
            throw new GuiguException(ResultCodeEnum.ROB_NEW_ORDER_FAIL);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                // 如果 lock 由当前线程持有，说明锁没有过期自动释放，手动释放锁
                lock.unlock();
            }
        }
        return true;
    }

    /**
     * 查询乘客执行中订单基本信息
     *
     * @param customerId
     * @return
     */
    @Override
    public CurrentOrderInfoVo searchCustomerCurrentOrder(Long customerId) {
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getCustomerId, customerId);
        // 如果订单状态是：已接单、司机已到达、更新购物车信息、开始服务、结束服务、未付款，乘客端需要显示当前订单信息
        // 处于等待接单状态的订单，已经由下单页面显示，这里不需要显示
        // 处于已付款、完成、未接单取消订单、不存在状态的订单，这里不需要显示
        List<Integer> statusList = Arrays.asList(
                OrderStatus.ACCEPTED.getStatus(),
                OrderStatus.DRIVER_ARRIVED.getStatus(),
                OrderStatus.UPDATE_CART_INFO.getStatus(),
                OrderStatus.START_SERVICE.getStatus(),
                OrderStatus.END_SERVICE.getStatus(),
                OrderStatus.UNPAID.getStatus());
        wrapper.in(OrderInfo::getStatus, statusList);
        // 创建时间倒序
        wrapper.orderByDesc(OrderInfo::getCreateTime);
        // 限制查询一条记录，结合上面的按照创建时间倒序，就能查询到最新的订单
        wrapper.last("limit 1");
        OrderInfo orderInfo = this.getOne(wrapper);
        CurrentOrderInfoVo currentOrderInfoVo = new CurrentOrderInfoVo();
        if (orderInfo != null) {
            currentOrderInfoVo.setOrderId(orderInfo.getId());
            currentOrderInfoVo.setStatus(orderInfo.getStatus());
            currentOrderInfoVo.setIsHasCurrentOrder(true);
        } else {
            currentOrderInfoVo.setIsHasCurrentOrder(false);
        }
        return currentOrderInfoVo;
    }

    /**
     * 查询司机执行中订单基本信息
     *
     * @param driverId
     * @return
     */
    @Override
    public CurrentOrderInfoVo searchDriverCurrentOrder(Long driverId) {
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getDriverId, driverId);
        // 如果订单状态是：已接单、司机已到达、更新购物车信息、开始服务、结束服务，司机端需要显示当前订单信息
        List<Integer> statusList = Arrays.asList(
                OrderStatus.ACCEPTED.getStatus(),
                OrderStatus.DRIVER_ARRIVED.getStatus(),
                OrderStatus.UPDATE_CART_INFO.getStatus(),
                OrderStatus.START_SERVICE.getStatus(),
                OrderStatus.END_SERVICE.getStatus());
        wrapper.in(OrderInfo::getStatus, statusList);
        // 创建时间倒序
        wrapper.orderByDesc(OrderInfo::getCreateTime);
        // 限制查询一条记录，结合上面的按照创建时间倒序，就能查询到最新的订单
        wrapper.last("limit 1");
        OrderInfo orderInfo = this.getOne(wrapper);
        CurrentOrderInfoVo currentOrderInfoVo = new CurrentOrderInfoVo();
        if (orderInfo != null) {
            currentOrderInfoVo.setOrderId(orderInfo.getId());
            currentOrderInfoVo.setStatus(orderInfo.getStatus());
            currentOrderInfoVo.setIsHasCurrentOrder(true);
        } else {
            currentOrderInfoVo.setIsHasCurrentOrder(false);
        }
        return currentOrderInfoVo;
    }

    /**
     * 接单司机到达代驾订单起始点
     * @param orderId
     * @param driverId
     * @return
     */
    @Override
    @Transactional
    public Boolean driverArriveStartLocation(Long orderId, Long driverId) {
        // 更新订单状态为：司机已到达，更新司机到达时间
        boolean result = this.lambdaUpdate()
                .eq(OrderInfo::getId, orderId)
                .eq(OrderInfo::getDriverId, driverId)
                .set(OrderInfo::getStatus, OrderStatus.DRIVER_ARRIVED.getStatus())
                .set(OrderInfo::getArriveTime, new Date())
                .update();

        // 记录订单状态日志到数据库
        if (result) {
            this.log(orderId, OrderStatus.DRIVER_ARRIVED.getStatus());
        } else {
            throw new GuiguException(ResultCodeEnum.UPDATE_ERROR);
        }
        return true;
    }

    /**
     * 更新代驾车辆信息
     * @param updateOrderCartForm
     * @return
     */
    @Override
    @Transactional
    public Boolean updateOrderCar(UpdateOrderCartForm updateOrderCartForm) {
        boolean update = this.lambdaUpdate()
                .eq(OrderInfo::getId, updateOrderCartForm.getOrderId())
                .eq(OrderInfo::getDriverId, updateOrderCartForm.getDriverId())
                .set(OrderInfo::getStatus, OrderStatus.UPDATE_CART_INFO.getStatus())
                .set(OrderInfo::getCarLicense, updateOrderCartForm.getCarLicense())
                .set(OrderInfo::getCarType, updateOrderCartForm.getCarType())
                .set(OrderInfo::getCarFrontUrl, updateOrderCartForm.getCarFrontUrl())
                .set(OrderInfo::getCarBackUrl, updateOrderCartForm.getCarBackUrl())
                .update();
        if (update) {
            this.log(updateOrderCartForm.getOrderId(), OrderStatus.UPDATE_CART_INFO.getStatus());
        } else {
            throw new GuiguException(ResultCodeEnum.UPDATE_ERROR);
        }
        return true;
    }

    /**
     * 开始代驾服务
     * @param startDriveForm
     * @return
     */
    @Override
    @Transactional
    public Boolean startDrive(StartDriveForm startDriveForm) {
        // 更新订单状态为：开始服务，更新开始服务时间
        boolean result = this.lambdaUpdate()
                .eq(OrderInfo::getId, startDriveForm.getOrderId())
                .eq(OrderInfo::getDriverId, startDriveForm.getDriverId())
                .set(OrderInfo::getStatus, OrderStatus.START_SERVICE.getStatus())
                .set(OrderInfo::getStartServiceTime, new Date())
                .update();
        if (result) {
            // 记录订单状态日志到数据库
            this.log(startDriveForm.getOrderId(), OrderStatus.START_SERVICE.getStatus());

            // 初始化订单监控统计记录
            OrderMonitor orderMonitor = new OrderMonitor();
            orderMonitor.setOrderId(startDriveForm.getOrderId());
            orderMonitorService.saveOrderMonitor(orderMonitor);
        } else {
            throw new GuiguException(ResultCodeEnum.UPDATE_ERROR);
        }
        return true;
    }

    /**
     * 根据时间获取订单数量
     * @param startTime
     * @param endTime
     * @param driverId
     * @return
     */
    @Override
    public Long getOrderNumByTime(String startTime, String endTime, Long driverId) {
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        // MyBatis Plus 中的 between 查询默认是闭区间的，即包括边界值
        // wrapper.between(OrderInfo::getStartServiceTime, startTime, endTime);
        // 避免边界值开始代驾服务的订单被重复查询，使用左闭右开区间
        wrapper.ge(OrderInfo::getStartServiceTime, startTime);
        wrapper.lt(OrderInfo::getStartServiceTime, endTime);
        wrapper.eq(OrderInfo::getDriverId, driverId);
        return this.count(wrapper);
    }

    /**
     * 结束代驾服务更新数据库表信息
     * @param updateOrderBillForm
     * @return
     */
    @Override
    @Transactional
    public Boolean endDrive(UpdateOrderBillForm updateOrderBillForm) {
        // 更新订单信息
        boolean result = this.lambdaUpdate()
                .eq(OrderInfo::getId, updateOrderBillForm.getOrderId())
                .eq(OrderInfo::getDriverId, updateOrderBillForm.getDriverId())
                .set(OrderInfo::getStatus, OrderStatus.END_SERVICE.getStatus())
                .set(OrderInfo::getEndServiceTime, new Date())
                .set(OrderInfo::getRealDistance, updateOrderBillForm.getRealDistance())
                .set(OrderInfo::getRealAmount, updateOrderBillForm.getOrderAmount())
                .set(OrderInfo::getFavourFee, updateOrderBillForm.getFavourFee())
                .update();
        if (result) {
            // 记录订单状态日志到数据库
            this.log(updateOrderBillForm.getOrderId(), OrderStatus.END_SERVICE.getStatus());

            // 保存实际账单信息
            OrderBill orderBill = new OrderBill();
            BeanUtils.copyProperties(updateOrderBillForm, orderBill);
            orderBill.setPayAmount(updateOrderBillForm.getOrderAmount());
            BigDecimal longDistanceFee = updateOrderBillForm.getExceedLongDistancePrice().multiply(updateOrderBillForm.getExceedLongDistance());
            orderBill.setLongDistanceFee(longDistanceFee);
            BigDecimal distanceFee = updateOrderBillForm.getBaseDistanceFee().add(longDistanceFee);
            orderBill.setDistanceFee(distanceFee);
            BigDecimal waitFee = updateOrderBillForm.getExceedWaitMinutePrice().multiply(BigDecimal.valueOf(updateOrderBillForm.getExceedWaitMinute()));
            orderBill.setWaitFee(waitFee);
            orderBill.setRewardFee(updateOrderBillForm.getRewardAmount());
            orderBill.setCouponAmount(BigDecimal.ZERO);
            orderBillMapper.insert(orderBill);

            // 保存分账数据
            OrderProfitsharing orderProfitsharing = new OrderProfitsharing();
            BeanUtils.copyProperties(updateOrderBillForm, orderProfitsharing);
            orderProfitsharing.setRuleId(updateOrderBillForm.getProfitsharingRuleId());
            // 分账状态，1-未分账，2-已分账
            orderProfitsharing.setStatus(1);
            orderProfitsharingMapper.insert(orderProfitsharing);
        } else {
            throw new GuiguException(ResultCodeEnum.UPDATE_ERROR);
        }
        return true;
    }

    /**
     * 分页查询乘客订单列表
     * @param pageParam
     * @param customerId
     * @return
     */
    @Override
    public PageVo findCustomerOrderPage(Page<OrderInfo> pageParam, Long customerId) {
        IPage<OrderListVo> page = orderInfoMapper.selectCustomerOrderPage(pageParam, customerId);
        return new PageVo(page.getRecords(), page.getPages(), page.getTotal());
    }

    /**
     * 分页查询司机订单列表
     * @param pageParam
     * @param driverId
     * @return
     */
    @Override
    public PageVo findDriverOrderPage(Page<OrderInfo> pageParam, Long driverId) {
        Page<OrderInfo> orderInfoPage = this.page(pageParam, new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getDriverId, driverId));
        List<OrderInfo> records = orderInfoPage.getRecords();
        List<OrderListVo> collect = records.stream().map(item -> {
            OrderListVo orderListVo = new OrderListVo();
            BeanUtils.copyProperties(item, orderListVo);
            orderListVo.setAmount(item.getStatus() >= 7 ? item.getRealAmount() : item.getExpectAmount());
            return orderListVo;
        }).collect(Collectors.toList());
        return new PageVo(collect, orderInfoPage.getPages(), orderInfoPage.getTotal());
    }

    /**
     * 根据订单 ID 查询订单账单信息
     * @param orderId
     * @return
     */
    @Override
    public OrderBillVo getOrderBillInfo(Long orderId) {
        OrderBill orderBill = orderBillMapper.selectOne(new LambdaQueryWrapper<OrderBill>().eq(OrderBill::getOrderId, orderId));
        OrderBillVo orderBillVo = new OrderBillVo();
        if (orderBill != null) {
            BeanUtils.copyProperties(orderBill, orderBillVo);
        }
        return orderBillVo;
    }

    /**
     * 根据订单 ID 查询订单分账信息
     * @param orderId
     * @return
     */
    @Override
    public OrderProfitsharingVo getOrderProfitsharing(Long orderId) {
        OrderProfitsharing orderProfitsharing = orderProfitsharingMapper.selectOne(new LambdaQueryWrapper<OrderProfitsharing>().eq(OrderProfitsharing::getOrderId, orderId));
        OrderProfitsharingVo orderProfitsharingVo = new OrderProfitsharingVo();
        if (orderProfitsharing != null) {
            BeanUtils.copyProperties(orderProfitsharing, orderProfitsharingVo);
        }
        return orderProfitsharingVo;
    }

    /**
     * 发送订单的账单信息给乘客
     * @param orderId
     * @param driverId
     * @return
     */
    @Override
    public Boolean sendOrderBillInfo(Long orderId, Long driverId) {
        boolean updated = this.lambdaUpdate().eq(OrderInfo::getId, orderId)
                .eq(OrderInfo::getDriverId, driverId)
                .set(OrderInfo::getStatus, OrderStatus.UNPAID.getStatus())
                .update();
        if (updated) {
            // 记录订单状态日志到数据库
            this.log(orderId, OrderStatus.UNPAID.getStatus());
        } else {
            throw new GuiguException(ResultCodeEnum.UPDATE_ERROR);
        }
        return true;
    }

    /**
     * 查询订单支付信息
     * @param orderNo
     * @param customerId
     * @return
     */
    @Override
    public OrderPayVo getOrderPayVo(String orderNo, Long customerId) {
        // 写法一：手动编写 SQL，使用联表查询
        OrderPayVo orderPayVo = orderInfoMapper.selectOrderPayVo(orderNo, customerId);
        if (orderPayVo != null) {
            orderPayVo.setContent(orderPayVo.getStartLocation() + "-->" + orderPayVo.getEndLocation());
        }
        return orderPayVo;

        // 写法二：不使用联表查询
        /*OrderInfo orderInfo = this.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, orderNo).eq(OrderInfo::getCustomerId, customerId));
        OrderPayVo orderPayVo = new OrderPayVo();
        if (orderInfo != null) {
            OrderBill orderBill = orderBillMapper.selectOne(new LambdaQueryWrapper<OrderBill>().eq(OrderBill::getOrderId, orderInfo.getId()));
            BeanUtils.copyProperties(orderInfo, orderPayVo);
            BeanUtils.copyProperties(orderBill, orderPayVo);
            orderPayVo.setContent(orderInfo.getStartLocation() + "-->" + orderInfo.getEndLocation());
        }
        return orderPayVo;*/
    }

    /**
     * 更新订单支付状态
     * @param orderNo
     * @return
     */
    @Override
    @Transactional
    public Boolean updateOrderPayStatus(String orderNo) {
        // 查询订单支付状态，如果已经更新为 7（已付款），则直接返回 true
        OrderInfo orderInfo = this.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, orderNo));
        if (orderInfo == null || OrderStatus.PAID.getStatus() == orderInfo.getStatus().intValue()) {
            return true;
        }

        boolean updated = this.lambdaUpdate().eq(OrderInfo::getOrderNo, orderNo)
                .set(OrderInfo::getStatus, OrderStatus.PAID.getStatus())
                .set(OrderInfo::getPayTime, new Date())
                .update();
        if (updated) {
            // 记录订单状态日志到数据库
            this.log(orderInfo.getId(), OrderStatus.PAID.getStatus());
        } else {
            throw new GuiguException(ResultCodeEnum.UPDATE_ERROR);
        }
        return true;
    }

    /**
     * 获取订单的系统奖励
     * @param orderNo
     * @return
     */
    @Override
    public OrderRewardVo getOrderRewardFee(String orderNo) {
        // 查询订单信息
        OrderInfo orderInfo = this.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, orderNo));
        // 查询订单的账单信息
        OrderBill orderBill = orderBillMapper.selectOne(new LambdaQueryWrapper<OrderBill>().eq(OrderBill::getOrderId, orderInfo.getId()));
        // 封装结果并返回
        OrderRewardVo orderRewardVo = new OrderRewardVo();
        orderRewardVo.setOrderId(orderInfo.getId());
        orderRewardVo.setDriverId(orderInfo.getDriverId());
        orderRewardVo.setRewardFee(orderBill.getRewardFee());
        return orderRewardVo;
    }

    /**
     * 根据订单 ID 取消订单
     * @param orderId
     */
    @Override
    @Transactional
    public void cancelOrder(Long orderId) {
        OrderInfo orderInfo = this.getById(orderId);
        if (OrderStatus.WAITING_ACCEPT.getStatus() == orderInfo.getStatus().intValue()) {
            // 订单状态为待接单，而且超过 15 分钟没有司机接单，则取消订单
            orderInfo.setStatus(OrderStatus.CANCEL_ORDER.getStatus());
            boolean updated = this.updateById(orderInfo);
            if (updated) {
                // 记录订单状态日志到数据库
                this.log(orderId, OrderStatus.CANCEL_ORDER.getStatus());
                // 删除 Redis 中当前订单的待接单标识
                redisTemplate.delete(RedisConstant.ORDER_ACCEPT_MARK + orderId);
            }
        }
    }

    /**
     * 更新订单优惠券金额
     * @param orderId
     * @param couponAmount
     * @return
     */
    @Override
    public Boolean updateOrderCouponAmount(Long orderId, BigDecimal couponAmount) {
        // 更新订单账单表中的优惠券金额和支付金额
        int updatedRowNum = orderBillMapper.updateCouponAmount(orderId, couponAmount);
        if (updatedRowNum == 0) {
            throw new GuiguException(ResultCodeEnum.UPDATE_ERROR);
        }
        return true;
    }
}
